package com.stockz.downloaderx;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.OrderComparator;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.stockz.core.manager.ConfigurationManager;
import com.stockz.core.model.Exchange;
import com.stockz.core.model.Scrip;
import com.stockz.core.util.CoreConstant;
import com.stockz.core.util.CoreUtil;
import com.stockz.core.util.SpringUtil;
import com.stockz.downloaderx.Downloader.Callback;
import com.stockz.downloaderx.util.DownloaderConstant;

@Component
public class DownloadManager{
	private static Logger logger = Logger.getLogger(DownloadManager.class);
	
	private List<BreadthDownloader> downloaderList;
	private List<Callback> callbackList;
	private List<Exchange> exchangeList; //should get this from settings
	private static boolean locked;
	
	@Autowired
	private ConfigurationManager configurationManager;
	
	
	public void init() throws Exception {
		downloaderList = new ArrayList<BreadthDownloader>();
		downloaderList.addAll(SpringUtil.getBeansOfType(BreadthDownloader.class));
		OrderComparator.sort(downloaderList);
		
		callbackList = new ArrayList<Callback>();
		callbackList.addAll(SpringUtil.getBeansOfType(Callback.class));
		OrderComparator.sort(callbackList);
	}

	public static void lock(){
		locked = true;
	}
	
	public static void unlock(){
		locked = false;
	}
	public synchronized void download(Exchange exchange, Date startDate, Date endDate,
			List<Callback> callbackList) {
		
	}

	public synchronized void download(Scrip scrip, Date startDate, Date endDate,
			List<Callback> callbackList) {
		
	}
	/**
	 * Blocks untill all downloads are cancelled
	 */
	public void cancelAllDownloads(){
		boolean alive = true;
		while(alive){
			alive = false;
			if(downloaderList != null && !downloaderList.isEmpty()){
				for(Downloader downloader : downloaderList){
					if(downloader !=  null && downloader.isRunning()){
						alive = true;
						downloader.cancel();
					}
				}
			}else{
				alive = false;
			}
		}
	}
	
	@Scheduled(cron="00 * * * * *")
	public void download(){
		if(locked){
			return;
		}else{
			locked = true;
			try{
				if(downloaderList == null || callbackList == null){
					init();
				}
				fallbackDownload(0);
			}catch(Throwable t){
				//logger.error("Error in downloader",t);
			}finally{
				locked = false;
			}
		}
	}
	
	private void fallbackDownload(int index){
		if(downloaderList != null
				&& index >= 0
				&& index < downloaderList.size()){
			BreadthDownloader downloader = downloaderList.get(index);
			try{
				exchangeList = getConfiguredExchangeList();
				if(exchangeList != null && !exchangeList.isEmpty()){
					Date today = new Date();
					for(Exchange exchange : exchangeList){
						downloader.download(exchange, CoreUtil.format(getLastDownloadDate(exchange)), CoreUtil.format(today), callbackList);
					}
				}
			}catch(Throwable t){
			//	logger.error(downloader.getClass().getCanonicalName()
				//		+" failed, falling back...",t);
				fallbackDownload(index+1);
			}
		}else{
	//		logger.info("Downloader List exhausted. " +
	//				"Can not download any data.");
		}
	}
	
	
	//For now just using hardcoded BSE exchange
	//Should get this list from user settings 
	public List<Exchange> getConfiguredExchangeList(){
		if(exchangeList == null)
			exchangeList = new ArrayList<Exchange>();
		if(exchangeList.isEmpty()){
			Exchange bse = new Exchange();
			bse.setCode("BSE");
			bse.setName("Bombay Stock Exchange");
			exchangeList.add(bse);
		}
		
		return exchangeList;
	}
	
	public Date getLastDownloadDate(Exchange exchange){
		//Should first check the map which should be kept in barManager
		return getLastDownloadDate();
	}
	
	@SuppressWarnings("deprecation")
	public Date getLastDownloadDate(){
	//	logger.info("getLastDownloadDate called");
		Date lastDownloadDate = null;
		try {
			String stringDate = (String)configurationManager.getValue(
					DownloaderConstant.LAST_BSE_BREDTH_DOWNLOAD_DATE);
			if(StringUtils.hasText(stringDate)){
				lastDownloadDate = CoreConstant.dateFormat.parse(stringDate);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(lastDownloadDate == null){
			logger.warn("Last download date not found, using default");
			lastDownloadDate = new Date(2009-1900,0,1);
		/*	Calendar cal = Calendar.getInstance();
			cal.add(Calendar.MONTH, -1);
			lastDownloadDate = cal.getTime();*/
		}
		logger.info("Last download date : "+lastDownloadDate);
		return lastDownloadDate;
	}
	
}
